#include "stdinclude.h"

#include "utils/win/winConsole.h"


WinConsole::WinConsole(void)
{
#ifdef _DEBUG
	HWND hwnd = ::GetConsoleWindow();
	if (hwnd==NULL)
		::AllocConsole();
#endif

	// obtain handle to stdout
	this->stdoutHandle = ::GetStdHandle(STD_OUTPUT_HANDLE);
	this->stdinHandle = ::GetStdHandle(STD_INPUT_HANDLE);
	this->stderrHandle = ::GetStdHandle(STD_ERROR_HANDLE);
	_assert(INVALID_HANDLE_VALUE != this->stdoutHandle);
	_assert(INVALID_HANDLE_VALUE != this->stdinHandle);
	_assert(INVALID_HANDLE_VALUE != this->stderrHandle);
}


WinConsole::~WinConsole(void)
{
#ifdef _DEBUG
	HWND hwnd = GetConsoleWindow();
	if (hwnd!=NULL)
		::FreeConsole();
#endif

}




//------------------------------------------------------------------------------
/**
*/
void
WinConsole::print(const String& s)
{
	DWORD charsWritten;
	// a message from the main thread
	WriteConsoleA(this->stdoutHandle, s.c_str(), s.length(), &charsWritten, NULL);
	#ifdef _DEBUG
	OutputDebugStringA(s.c_str());
	#endif
}


//------------------------------------------------------------------------------
/**
*/
void
WinConsole::error(const String& msg)
{    
	const char* appName = "???";
//    if (Core::CoreServer::HasInstance())
	{
  //      appName = Core::CoreServer::Instance()->GetAppName().c_str();
	}
	
	String str = StringTools::format("*** ERROR ***\nApplication: %s\nThread: %s\nError: %s", appName, "?", msg.c_str());
	DWORD charsWritten;
	WriteConsoleA(this->stderrHandle, str.c_str(), str.length(), &charsWritten, NULL);
	
	OsTools::Error(str.c_str());
}

//------------------------------------------------------------------------------
/**
*/
void
WinConsole::warning(const String& s)
{
	DWORD charsWritten;

	// a message from the main thread
	WriteConsoleA(this->stderrHandle, s.c_str(), s.length(), &charsWritten, NULL);
	#ifdef _DEBUG
	OutputDebugStringA(s.c_str());
	#endif
}

//------------------------------------------------------------------------------
/**
	Since we are blocking the app waiting for user input, we always provide 
	input.
*/
bool
WinConsole::hasInput()
{
	const DWORD bufNumInputs = 16;
	DWORD  numEvents = 0;
	INPUT_RECORD buf[bufNumInputs];
	BOOL success = PeekConsoleInput(this->stdinHandle, buf, bufNumInputs, &numEvents);
	DWORD dw = GetLastError(); 

	if (success && (numEvents > 0))
	{
		IndexT i;
		for (i = 0; i < numEvents; i++)
		{
			if (buf[i].EventType == KEY_EVENT)
			{
				return true;
			}
		}
	}    
	return false;
}

//------------------------------------------------------------------------------
/**
	Get user input from the console.
*/
String
WinConsole::getInput()
{
	String result;
	const DWORD bufNumChars = 4096;
	DWORD numCharsRead = 0;
	CHAR buf[bufNumChars];
	BOOL success = ReadConsoleA(this->stdinHandle, buf, bufNumChars, &numCharsRead, NULL);
	if (success && (numCharsRead > 0))
	{
		result.assign(buf, numCharsRead);
		result = StringTools::rtrim(result);
		//result.Set(buf, numCharsRead);
		//result.TrimRight("\n\r");
	}
	return result;
}


